ποΈGitΠ―ΡΠ°ποΈ
feature/connections/README.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 7.01 KB
T383838:feature:connections
Overview
The T383838:feature:connections module provides the device discovery and connection management screen. It enables users to scan for and connect to Meshtastic radios over BLE, USB serial, and TCP/NSD (network service discovery). The T383838ScannerViewModel is platform-neutral; Android and JVM subclasses supply platform-specific bonding and permission workflows.
Targets: Android Β· JVM (Desktop) Β· iOS (via T383838meshtastic.kmp.feature convention plugin)
Key Responsibilities
β’ Scan for BLE devices and merge results with previously bonded devices (bonded first, then discovery order)
β’ Enumerate USB serial devices (CH340, FTDI, CP21xx, etc.) with permission gating on Android
β’ Discover TCP/NSD services and manage recent manual TCP addresses
β’ Surface a single-choice transport selector (BLE / Network / USB) whose active pane persists to DataStore
β’ Manage the full connection flow: bond β connect β disconnect
β’ Show connection status and progress while a device is being configured
Source Structure
T282828
src/
βββ commonMain/kotlin/org/meshtastic/feature/connections/
β βββ ScannerViewModel.kt β platform-neutral ViewModel
β βββ Constants.kt
β βββ model/
β β βββ DeviceListEntry.kt β sealed: Ble | Usb | Tcp | Mock | Replay
β β βββ DiscoveredDevices.kt β GetDiscoveredDevicesUseCase interface + result
β βββ domain/usecase/
β β βββ CommonGetDiscoveredDevicesUseCase.kt
β β βββ TcpDiscoveryHelpers.kt
β β βββ UsbScanner.kt β common USB scanner interface
β βββ navigation/
β β βββ ConnectionsNavigation.kt
β βββ ui/
β β βββ ConnectionsScreen.kt
β β βββ components/
β β βββ ConnectingDeviceInfo.kt
β β βββ ConnectionActionButton.kt
β β βββ CurrentlyConnectedInfo.kt
β β βββ DeviceList.kt / DeviceListItem.kt / DeviceSectionHeader.kt
β β βββ DisconnectButton.kt
β β βββ EmptyStateContent.kt
β β βββ TransportSelector.kt
β βββ di/
β βββ FeatureConnectionsModule.kt
βββ androidMain/kotlin/
β βββ AndroidScannerViewModel.kt β overrides bond/permission requests
β βββ domain/usecase/AndroidGetDiscoveredDevicesUseCase.kt
βββ jvmMain/kotlin/
βββ JvmScannerViewModel.kt
βββ domain/usecase/JvmGetDiscoveredDevicesUseCase.kt
Key Types
T383838DeviceListEntry (sealed class)
T282828
Tff7b72sealed Tff7b72class T56d364DeviceListEntry Tb4b4b4{
Tff7b72data Tff7b72class T56d364BleTb4b4b4(Te6edf3deviceTb4b4b4: Te6edf3BleDeviceTb4b4b4, Te6edf3bondedTb4b4b4: Tffa657BooleanTb4b4b4, Te6edf3nodeTb4b4b4: Te6edf3Node?Tb4b4b4) Tb4b4b4: Te6edf3DeviceListEntryTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364UsbTb4b4b4(Te6edf3usbDataTb4b4b4: Te6edf3UsbDeviceDataTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3fullAddressTb4b4b4: Tffa657StringTb4b4b4, Tb4b4b4.Tb4b4b4.Tb4b4b4.Tb4b4b4) Tb4b4b4: Te6edf3DeviceListEntryTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364TcpTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3fullAddressTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nodeTb4b4b4: Te6edf3Node?Tb4b4b4) Tb4b4b4: Te6edf3DeviceListEntryTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364MockTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nodeTb4b4b4: Te6edf3Node?Tb4b4b4) Tb4b4b4: Te6edf3DeviceListEntryTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364ReplayTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nodeTb4b4b4: Te6edf3Node?Tb4b4b4) Tb4b4b4: Te6edf3DeviceListEntryTb4b4b4(Tb4b4b4)
Tff7b72abstract Tff7b72val Te6edf3addressTb4b4b4: Tffa657String T8b949e// strips transport prefix
Tff7b72abstract Tff7b72fun Td2a8ffcopyTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3Node?Tb4b4b4)Tb4b4b4: Te6edf3DeviceListEntry
Tb4b4b4}
Address format conventions: BLE β T383838x<MAC>, USB β T383838s<path>, TCP β T383838t<host:port>, Mock β T383838m, Replay β T383838r.
T383838ScannerViewModel
Platform-neutral ViewModel. Exposes:
T282828
T8b949e// Device lists
Tff7b72val Te6edf3bleDevicesForUiTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3DeviceListEntryTff7b72>Tff7b72>
Tff7b72val Te6edf3usbDevicesForUiTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3DeviceListEntryTff7b72>Tff7b72>
Tff7b72val Te6edf3discoveredTcpDevicesForUiTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3DeviceListEntryTff7b72>Tff7b72>
Tff7b72val Te6edf3recentTcpDevicesForUiTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ListTff7b72<Te6edf3DeviceListEntryTff7b72>Tff7b72>
T8b949e// Scan state
Tff7b72val Te6edf3activeTransportTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3DeviceTypeTff7b72>
Tff7b72val Te6edf3isBleScanningTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72>
Tff7b72val Te6edf3isNetworkScanningTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72>
T8b949e// Connection
Tff7b72val Te6edf3connectionProgressTextTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72>
Tff7b72val Te6edf3selectedAddressFlowTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72>
T8b949e// Actions
Tff7b72fun Td2a8ffselectTransportTb4b4b4(Te6edf3typeTb4b4b4: Te6edf3DeviceTypeTb4b4b4)
Tff7b72fun Td2a8ffstartBleScanTb4b4b4(Tb4b4b4) Tff7b72/ Te6edf3stopBleScanTb4b4b4(Tb4b4b4) Tff7b72/ Te6edf3toggleBleScanTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffstartBleAutoScanTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffstartNetworkScanTb4b4b4(Tb4b4b4) Tff7b72/ Te6edf3stopNetworkScanTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffstartNetworkAutoScanTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffpersistNetworkAutoScanIntentTb4b4b4(Te6edf3enabledTb4b4b4: Tffa657BooleanTb4b4b4)
Tff7b72fun Td2a8ffconnectToManualAddressTb4b4b4(Te6edf3fullAddressTb4b4b4: Tffa657StringTb4b4b4)
Tff7b72fun Td2a8ffonSelectedTb4b4b4(Te6edf3entryTb4b4b4: Te6edf3DeviceListEntryTb4b4b4)Tb4b4b4: Tffa657Boolean T8b949e// false if bond/permission still pending
Tff7b72fun Td2a8ffdisconnectTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffaddRecentAddressTb4b4b4(Te6edf3addressTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4)
Tff7b72fun Td2a8ffremoveRecentAddressTb4b4b4(Te6edf3addressTb4b4b4: Tffa657StringTb4b4b4)
Android and JVM subclasses override T383838requestBonding(entry) and T383838requestPermission(entry) to perform OS-level Bluetooth pairing and USB permission dialogs respectively.
Navigation
T282828
T8b949e// Registration (in androidApp / desktopApp nav graph)
Tff7b72fun Td2a8ffEntryProviderScopeTff7b72<Te6edf3NavKeyTff7b72>Tb4b4b4.Te6edf3connectionsGraphTb4b4b4(Te6edf3backStackTb4b4b4: Te6edf3NavBackStackTff7b72<Te6edf3NavKeyTff7b72>Tb4b4b4) Tb4b4b4{
T8b949e// Registers ConnectionsRoute.Connections entry
T8b949e// Injects ScannerViewModel via Koin
Tb4b4b4}
Route: T383838ConnectionsRoute.Connections
Dependency Graph
Key Dependencies
T282828
feature:connections
βββ core:ble, core:network (transports)
βββ core:common, core:data, core:database, core:datastore, core:di
βββ core:domain, core:model, core:navigation
βββ core:prefs, core:resources, core:service, core:ui
βββ org.meshtastic:protobufs (Maven artifact)
βββ usb-serial-android (Android only)
<!--region graph-->
T282828
Te6edf3graph Te6edf3TB
:Te6edf3featureTb4b4b4:Te6edf3connectionsTff7b72[Te6edf3connectionsTff7b72]Tff7b72:::Te6edf3kmpTff7b72-Te6edf3feature
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3common
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Tff7b72data
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Tff7b72database
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3datastore
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3di
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Tff7b72domain
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3model
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3navigation
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3prefs
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3resources
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3service
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3ui
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3ble
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3network
:Te6edf3featureTb4b4b4:Te6edf3connections Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3testing
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3application Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3applicationTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3composeTff7b72-Te6edf3desktopTff7b72-Te6edf3application Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3feature Te6edf3fillTb4b4b4:Te6edf3#FFD6A5Tb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#9BF6FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3libraryTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#9BF6FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3test Te6edf3fillTb4b4b4:Te6edf3#A0C4FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3jvmTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#BDB2FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3feature Te6edf3fillTb4b4b4:Te6edf3#FFD6A5Tb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3libraryTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#FFC1CCTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#FFC1CCTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Tff7b72unknown Te6edf3fillTb4b4b4:Te6edf3#FFADADTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
<!--endregion-->
Served by rngit 1.5.0 - Generated in 0.08s